package com.zdp.nio.buffer;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Objects;

/**
 * Buffer 对象获取
 */
public class BufferMethod {
    /**
     * Nio Buffer的使用的大致流程：
     * 1. 获取 Buffer对象
     * 2. 写入数据 （如果要覆盖写入数据，就需要利用 mark() 和 reset()来操作）
     * 3. 切换Buffer模式 （切换为读模式）
     * 4. 读取数据 （可以使用 rewind()来重复读取Buffer）
     * 5. 切换Buffer模式 （切换为写模式）
     */
    public static void main(String[] args) {
        // 获取对象
        System.out.println("> 获取对象");
        IntBuffer intBuff = getIntBuff(20);
        // 写入数据
        System.out.println("> 写入数据");
        putData(new int[]{1,2,3,4,5},intBuff);
        // 切换模式
        System.out.println("> 写模式切换为读模式");
        writeToRead(intBuff);
        // 读取数据
        System.out.println("> 读取数据");
        readData(4,intBuff);
        // 重读数据
        System.out.println("> 重读数据");
        againRead(intBuff);
        // 读取数据的同时，做标记
        System.out.println("> 读取数据，并标记");
        marked(intBuff,5,3);
        // 重放标记数据
        System.out.println("> 重放标记数据");
        reset(intBuff);
        // 模式切换
        System.out.println("> 读模式切换为写模式");
//        readToWrite(intBuff);
        readToWriteCompact(intBuff);
    }

    /**
     * 读模式切换为写模式 使用 compact()方法（压缩缓冲区）
     * 压缩缓冲区好像是把之前buffer中的内容给压缩成了一块
     * @param intBuffer
     */
    public static void readToWriteCompact(IntBuffer intBuffer){
        intBuffer.compact();
        soutInfo(intBuffer);
    }

    /**
     * 重发 mark 存储的 Position值
     * @param intBuffer
     */
    public static void reset(IntBuffer intBuffer){
        // 重放数据
        intBuffer.reset();
        int data = intBuffer.get();
        System.out.println(String.format("读取的值为:%d,position:%d,capacity:%d,limit:%d",data,intBuffer.position(),intBuffer.capacity(),intBuffer.limit()));
        soutInfo(intBuffer);
    }

    /**
     * 记录 position 点 （无论读或者写都可以记录在某个时刻的position值）
     * 记录在 mark属性中，通过 reset() 来重放
     * @param intBuffer
     * @param size 要读取的数量
     * @param markedIndex 需要标记的位置
     */
    public static void marked(IntBuffer intBuffer,int size,int markedIndex){
        for(int i =0;i<size;i++){
            if( i == markedIndex){
                intBuffer.mark();
            }
            int data = intBuffer.get();
            System.out.println(String.format("读取的值为:%d,position:%d,capacity:%d,limit:%d",data,intBuffer.position(),intBuffer.capacity(),intBuffer.limit()));
        }
        soutInfo(intBuffer);
    }

    /**
     * 重置 position值，用于重读 Buffer
     * @param intBuffer
     */
    public static void againRead(Buffer intBuffer){
        // 重读操作 --> 处理 position 值
        intBuffer.rewind();
        soutInfo(intBuffer);
    }

    /**
     * 由读模式切换到 写入模式
     * @param intBuffer
     */
    public static void readToWrite(Buffer intBuffer){
        intBuffer.clear();
        soutInfo(intBuffer);
    }

    /**
     * 读取数据
     * @param size 读取的数据的个数
     * @param intBuffer
     */
    public static void readData(int size,IntBuffer intBuffer){
        for(int i =0;i<size;i++){
            int data = intBuffer.get();
            System.out.println(String.format("读取的值为:%d,position:%d,capacity:%d,limit:%d",data,intBuffer.position(),intBuffer.capacity(),intBuffer.limit()));
        }
        soutInfo(intBuffer);
    }

    public static void readData(int size, ByteBuffer intBuffer){
        for(int i =0;i<size;i++){
            int data = intBuffer.get();
            System.out.println(String.format("读取的值为:%d,position:%d,capacity:%d,limit:%d",data,intBuffer.position(),intBuffer.capacity(),intBuffer.limit()));
        }
        soutInfo(intBuffer);
    }


    /**
     * Buffer模式切换，由写模式 切换到 读模式
     * @param intBuffer
     */
    public static  void writeToRead(Buffer intBuffer){
        intBuffer.flip();
        soutInfo(intBuffer);
    }

    /**
     * 写入数据，观察 Buffer中变量的值
     * @param datas 要写入的数据
     * @param intBuffer {@link IntBuffer}
     */
    public static void putData(int[] datas,IntBuffer intBuffer){
        if(Objects.nonNull(datas) && datas.length != 0){
            for(int data : datas){
                intBuffer.put(data);
            }
        }
        soutInfo(intBuffer);
    }

    public static void putData(byte[] datas,ByteBuffer intBuffer){
        if(Objects.nonNull(datas) && datas.length != 0){
            for(byte data : datas){
                intBuffer.put(data);
            }
        }
        soutInfo(intBuffer);
    }

    /**
     * 获取 Buffer实例对象，实例对象被创建时处于写入模式
     * @param size Buffer容纳长度
     * @return Buffer实例对象
     */
    public static IntBuffer getIntBuff(int size){
        // 获取Buffer实例对象
        IntBuffer intBuffer = IntBuffer.allocate(size);
        soutInfo(intBuffer);
        return intBuffer;
    }

    public static void soutInfo(Buffer buffer){
        System.out.println("> capacity = " + buffer.capacity());
        System.out.println("> limit = " + buffer.limit());
        System.out.println("> position = " + buffer.position());
        System.out.println("> =========================================== < ");
    }
}
